﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotSpatial.Controls;
using DotSpatial.Topology;
using System.Windows.Forms;
using DotSpatial.Data;
using System.Diagnostics;

namespace HAGISV2
{
    public class HEditConceptFrame:HMapFunction
    {
        public HEditConceptFrame(IMap map)
            : base(map)
        {
            Configure();


        }

        #region 变量
                
        ConceptFrameLayer _thisLayer;
        //bool _islayerSelected;
        bool _isDraging;
        bool _isRevolve;
        bool _isTranslating;//是否平移
        bool _isNeedReGenerate;
        int _selectedPointIndex;//从零开始四角点四中点

        bool _isMoveEnd;

        Coordinate coordFirst, coordSecend;
        RectangleFrame _helpRectFrame;
        //四个辅助角点
        List<Coordinate> _helpFourCoordinates;
        //四个边线
        List<LineSegment> _helpFourSegment;

        #endregion

        #region 方法

        protected override void OnActivate()
        {
            base.OnActivate();
        }

        protected override void OnDraw(MapDrawArgs e)
        {
            if ((_thisLayer = this.InteractiveSystem.CurrentLayer as ConceptFrameLayer) == null || _standBy || !_thisLayer.IsPointLayerSelectedAndShow) return;
            if (_isMoveEnd) return;
            if (_helpFourCoordinates!=null&&_isNeedReGenerate)
            {
                System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
                System.Drawing.Point [] pts=new System.Drawing.Point[5];
                pts[0] = Map.ProjToPixel(_helpFourCoordinates[0]);
                pts[1] = Map.ProjToPixel(_helpFourCoordinates[1]);
                pts[2] = Map.ProjToPixel(_helpFourCoordinates[2]);
                pts[3] = Map.ProjToPixel(_helpFourCoordinates[3]);
                pts[4] = pts[0];
                gp.AddLines(pts);
                e.Graphics.DrawPath(new System.Drawing.Pen(System.Drawing.Color.HotPink, 3f), gp);
                gp.Dispose();
                Map.Invalidate();
            }
            else return;

            base.OnDraw(e);
        }

        protected override void OnMouseDown(GeoMouseArgs e)
        {
            if ((_thisLayer = this.InteractiveSystem.CurrentLayer as ConceptFrameLayer) == null || _standBy) return;

            if (e.Button == MouseButtons.Left)
            {
                Map.IsBusy = true;
                coordFirst = Map.PixelToProj(e.Location);
                _isDraging = false;
                _isRevolve = false;
                _isTranslating = false;
                _selectedPointIndex = -1;
                IEnvelope env;
                if (_thisLayer.ViewMode != FMAPVIEW.NORMAL) return;
                env = new Envelope(coordFirst);
                env.ExpandBy(Map.MapFrame.ViewExtents.Width / 200);
                Polygon p = (Polygon)env.ToPolygon();

                if (_thisLayer.IsPointLayerSelectedAndShow)
                {
                    for (int i = 0; i < _thisLayer.PtLayer.DataSet.Features.Count; i++)
                    {
                        if (p.Intersects((Point)_thisLayer.PtLayer.DataSet.Features[i].BasicGeometry))
                        {
                            _selectedPointIndex = i;
                            if (i != _thisLayer.PtLayer.DataSet.Features.Count - 1)
                            {
                                _isDraging = true;
                                _helpRectFrame = _thisLayer.RectFrame.Clone();
                                _helpFourCoordinates = new List<Coordinate>(_helpRectFrame.FourBounderCoordinates);
                                _helpFourSegment = _thisLayer.LeftTopRihgtBotLine;
                            }
                            else
                            {
                                _helpRectFrame = _thisLayer.RectFrame.Clone();
                                _isRevolve = true;
                            }
                            break;
                        }

                    }
                    if (!_isDraging&&!_isRevolve)
                    {
                        if (new Polygon((ILinearRing)_thisLayer.LnLayer.DataSet.Features[0].BasicGeometry).Contains(new DotSpatial.Topology.Point(coordFirst)))
                        {
                            _helpRectFrame = _thisLayer.RectFrame.Clone();
                            _isTranslating = true;
                        }
                        else
                        {
                            _thisLayer.ClearSelection();
                        }
                    }
                }
                else
                {
                    if (p.Intersects((ILinearRing)_thisLayer.LnLayer.DataSet.Features[0].BasicGeometry))
                    {
                        _thisLayer.PtLayer.DataSet.UpdateExtent();
                        _thisLayer.PtLayer.SelectAll();
                        _thisLayer.IsPointLayerSelectedAndShow = true;
                    }
                    else
                    {
                        _thisLayer.ClearSelection();
                    }
                    _helpRectFrame = null;
                }
            }

            if (_isDraging || _isTranslating || _isRevolve) _isMoveEnd = false;
            Map.Invalidate();
            //base.OnMouseDown(e);
        }

        protected override void OnMouseMove(GeoMouseArgs e)
        {
            if ((_thisLayer = this.InteractiveSystem.CurrentLayer as ConceptFrameLayer) == null || _standBy || !_thisLayer.IsPointLayerSelectedAndShow) return;
            _isNeedReGenerate = false;

            if (_isDraging)
            {
                _isNeedReGenerate = GetNewConceptFrame(e);

            }
            else if (_isTranslating)
            {
                _isNeedReGenerate = true;
                Vector offset = new Vector (Map.PixelToProj(e.Location) - coordFirst);
                if (offset.Length2D == 0) return;
                _helpRectFrame.LeftBottomCoordinate = (Coordinate)_thisLayer.RectFrame.LeftBottomCoordinate.Clone();
                _helpRectFrame.LeftBottomCoordinate += offset;
                _helpRectFrame.ReGenerate();
                _helpFourCoordinates = _helpRectFrame.FourBounderCoordinates;
            }
            else if (_isRevolve)
            {
                _isNeedReGenerate = true;
                Vector rotateVect = new Vector(Map.PixelToProj(e.Location) - _thisLayer.RectFrame.LeftBottomCoordinate);
                if (rotateVect.Y >= 0)
                    _helpRectFrame.Rotation = Math.Acos(rotateVect.X / rotateVect.Length2D) / Math.PI * 180;
                else
                    _helpRectFrame.Rotation = 0 - Math.Acos(rotateVect.X / rotateVect.Length2D) / Math.PI * 180;
                _helpRectFrame.ReGenerate();
                _helpFourCoordinates = _helpRectFrame.FourBounderCoordinates;
            }
            Map.Invalidate();
            base.OnMouseMove(e);
        }

        protected override void OnMouseUp(GeoMouseArgs e)
        {
            if ((_thisLayer = this.InteractiveSystem.CurrentLayer as ConceptFrameLayer) == null || _standBy) return;
            Map.IsBusy = false;
            if (e.Button == MouseButtons.Left)
            {
                coordSecend = Map.PixelToProj(e.Location);
                if (coordSecend == coordFirst)
                {
                    return;
                }

                if (_isNeedReGenerate)
                {
                    if (_isDraging || _isTranslating || _isRevolve)
                    {
                        

                        this.InteractiveSystem.AskEditConceptFrame
                            (
                                 new EditConceptFrameEventArgs
                                (
                                _helpRectFrame.LeftBottomCoordinate.X,
                                _helpRectFrame.LeftBottomCoordinate.Y,
                                _helpRectFrame.Width,
                                _helpRectFrame.Height,
                                _helpRectFrame.Rotation
                                )
                             );

                        _helpRectFrame = null;
                    }

                    _isDraging = false;
                    _isRevolve = false;
                    _isTranslating = false;
                    _isNeedReGenerate = false;

                    if (_thisLayer.IsPointLayerSelectedAndShow)
                    {
                        _thisLayer.PtLayer.DataSet.UpdateExtent(); 
                        _thisLayer.PtLayer.SelectAll();
                    }

                }
                _isMoveEnd = true;
            }

            base.OnMouseUp(e);
        }

        protected override void OnMouseDoubleClick(GeoMouseArgs e)
        {
            base.OnMouseDoubleClick(e);
        }

        

        #endregion

        /// <summary>
        /// 生成新的辅助ConceptFrame
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        bool GetNewConceptFrame(GeoMouseArgs e)
        {
            if (_helpRectFrame == null)
            {
                _helpRectFrame = _thisLayer.RectFrame.Clone();
                _helpFourCoordinates = new List<Coordinate>( _helpRectFrame.FourBounderCoordinates);
                _helpFourSegment = _thisLayer.LeftTopRihgtBotLine;
            }
            Coordinate eCoord = Map.PixelToProj(e.Location);

            switch (_selectedPointIndex)
            {
                case 0://左下角点
                    _helpFourCoordinates[0] = eCoord;

                    if (_helpFourSegment[1].ProjectionFactor(eCoord) >= 1) return false;
                    _helpFourCoordinates[1] = _helpFourSegment[1].Project(eCoord);

                    if (_helpFourSegment[2].ProjectionFactor(eCoord) <= 0) return false;
                    _helpFourCoordinates[3] = _helpFourSegment[2].Project(eCoord);

                    _helpRectFrame.Width = _helpFourCoordinates[0].Distance(_helpFourCoordinates[3]);
                    _helpRectFrame.Height = _helpFourCoordinates[0].Distance(_helpFourCoordinates[1]);
                    _helpRectFrame.LeftBottomCoordinate = _helpFourCoordinates[0];

                    break;

                case 1://左上角点
                    _helpFourCoordinates[1] = eCoord;

                    if (_helpFourSegment[2].ProjectionFactor(eCoord) >= 1) return false;
                    _helpFourCoordinates[2] = _helpFourSegment[2].Project(eCoord);

                    if (_helpFourSegment[3].ProjectionFactor(eCoord) <= 0) return false;
                    _helpFourCoordinates[0] = _helpFourSegment[3].Project(eCoord);

                    _helpRectFrame.Width = _helpFourCoordinates[0].Distance(_helpFourCoordinates[3]);
                    _helpRectFrame.Height = _helpFourCoordinates[0].Distance(_helpFourCoordinates[1]);
                    _helpRectFrame.LeftBottomCoordinate = _helpFourCoordinates[0];

                    break;

                case 2://右上角点
                    _helpFourCoordinates[2] = eCoord;

                    if (_helpFourSegment[0].ProjectionFactor(eCoord) <= 0) return false;
                    _helpFourCoordinates[1] = _helpFourSegment[0].Project(eCoord);

                    if (_helpFourSegment[3].ProjectionFactor(eCoord) >= 1) return false;
                    _helpFourCoordinates[3] = _helpFourSegment[3].Project(eCoord);

                    _helpRectFrame.Width = _helpFourCoordinates[0].Distance(_helpFourCoordinates[3]);
                    _helpRectFrame.Height = _helpFourCoordinates[0].Distance(_helpFourCoordinates[1]);
                    //_helpRectFrame.LeftBottomCoordinate = _helpFourCoordinates[0];


                    break;

                case 3://右下角点
                    _helpFourCoordinates[3] = eCoord;

                    if (_helpFourSegment[1].ProjectionFactor(eCoord) <= 0) return false;
                    _helpFourCoordinates[2] = _helpFourSegment[1].Project(eCoord);

                    if (_helpFourSegment[0].ProjectionFactor(eCoord) >= 1) return false;
                    _helpFourCoordinates[0] = _helpFourSegment[0].Project(eCoord);

                    _helpRectFrame.Width = _helpFourCoordinates[0].Distance(_helpFourCoordinates[3]);
                    _helpRectFrame.Height = _helpFourCoordinates[0].Distance(_helpFourCoordinates[1]);
                    _helpRectFrame.LeftBottomCoordinate = _helpFourCoordinates[0];


                    break;

                case 4://左中点

                    if (_helpFourSegment[3].ProjectionFactor(eCoord) <= 0) return false;
                    _helpFourCoordinates[0] = _helpFourSegment[3].Project(eCoord);

                    if (_helpFourSegment[1].ProjectionFactor(eCoord) >= 1) return false;
                    _helpFourCoordinates[1] = _helpFourSegment[1].Project(eCoord);

                    _helpRectFrame.Width = _helpFourCoordinates[0].Distance(_helpFourCoordinates[3]);
                    _helpRectFrame.Height = _helpFourCoordinates[0].Distance(_helpFourCoordinates[1]);
                    _helpRectFrame.LeftBottomCoordinate = _helpFourCoordinates[0];


                    break;

                case 5://上中点
                    
                    if (_helpFourSegment[0].ProjectionFactor(eCoord) <= 0) return false;
                    _helpFourCoordinates[1] = _helpFourSegment[0].Project(eCoord);

                    if (_helpFourSegment[2].ProjectionFactor(eCoord) >= 1) return false;
                    _helpFourCoordinates[2] = _helpFourSegment[2].Project(eCoord);

                    _helpRectFrame.Width = _helpFourCoordinates[0].Distance(_helpFourCoordinates[3]);
                    _helpRectFrame.Height = _helpFourCoordinates[0].Distance(_helpFourCoordinates[1]);
                    //_helpRectFrame.LeftBottomCoordinate = _helpFourCoordinates[0];

                    break;

                case 6://右中点
                    
                    if (_helpFourSegment[1].ProjectionFactor(eCoord) <= 0) return false;
                    _helpFourCoordinates[2] = _helpFourSegment[1].Project(eCoord);

                    if (_helpFourSegment[3].ProjectionFactor(eCoord) >= 1) return false;
                    _helpFourCoordinates[3] = _helpFourSegment[3].Project(eCoord);

                    _helpRectFrame.Width = _helpFourCoordinates[0].Distance(_helpFourCoordinates[3]);
                    _helpRectFrame.Height = _helpFourCoordinates[0].Distance(_helpFourCoordinates[1]);
                    //_helpRectFrame.LeftBottomCoordinate = _helpFourCoordinates[0];

                    break;

                case 7://下中点
                    
                    if (_helpFourSegment[0].ProjectionFactor(eCoord) >= 1) return false;
                    _helpFourCoordinates[0] = _helpFourSegment[0].Project(eCoord);

                    if (_helpFourSegment[2].ProjectionFactor(eCoord) <= 0) return false;
                    _helpFourCoordinates[3] = _helpFourSegment[2].Project(eCoord);

                    _helpRectFrame.Width = _helpFourCoordinates[0].Distance(_helpFourCoordinates[3]);
                    _helpRectFrame.Height = _helpFourCoordinates[0].Distance(_helpFourCoordinates[1]);
                    _helpRectFrame.LeftBottomCoordinate = _helpFourCoordinates[0];

                    break;

                default:
                    break;
            }


            return true;
        }










        private void Configure()
        {
            YieldStyle = (YieldStyles.LeftButton | YieldStyles.RightButton | YieldStyles.Keyboard);

        }
    }
}
